package com.example.archive.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.archive.entity.Archive;
import com.example.archive.entity.Category;
import com.example.archive.entity.Tag;
import com.example.archive.mapper.CategoryMapper;
import com.example.archive.mapper.TagMapper;
import com.example.archive.service.ArchiveService;
import com.example.archive.service.ElasticsearchArchiveService;
import com.example.archive.util.PageParam;
import com.example.archive.util.Result;
import com.example.archive.util.UserContext;
import com.example.archive.util.NLPProcessor;
import com.example.archive.config.FileUploadConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import java.io.File;

/**
 * 档案管理控制器
 * 提供档案的增删改查、文件上传等核心功能
 * 支持NLP自动分类和标签生成
 * 集成Elasticsearch全文搜索功能
 */
@RestController
@RequestMapping("/archive")
public class ArchiveController {
    private static final Logger logger = LoggerFactory.getLogger(ArchiveController.class);

    @Autowired
    private ArchiveService archiveService;

    @Autowired
    private ElasticsearchArchiveService elasticsearchArchiveService;

    @Autowired
    private NLPProcessor nlpProcessor;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private TagMapper tagMapper;

    @PostMapping("/add")
    public Result<Boolean> addArchive(@RequestBody Archive archive) {
        return archiveService.addArchive(archive);
    }

    @PostMapping("/upload")
    public Result<Archive> uploadArchive(
            @RequestParam(value = "file", required = false) MultipartFile file,
            @RequestParam("title") String title,
            @RequestParam("physicalLocation") String physicalLocation,
            @RequestParam("archiveType") String archiveType,
            @RequestParam("securityLevel") String securityLevel,
            @RequestParam("visibleScope") String visibleScope,
            @RequestParam(value = "ocrContent", required = false) String ocrContent) {

        // 验证：文件和OCR内容至少需要提供一个
        boolean hasFile = file != null && !file.isEmpty();
        boolean hasOcrContent = ocrContent != null && !ocrContent.trim().isEmpty();
        
        if (!hasFile && !hasOcrContent) {
            return Result.fail(400, "请上传文件或提供OCR识别内容，两者至少选择一个");
        }

        try {
            String filePath = null;
            String extractedText = "";
            
            // 如果有文件，处理文件上传
            if (hasFile) {
                // 获取原始文件名
                String fileName = file.getOriginalFilename();
                // 生成唯一文件名，防止重名冲突
                String newFileName = UUID.randomUUID().toString() + "_" + fileName;
                
                // 使用配置类获取上传路径
                String uploadPath = FileUploadConfig.getUploadPath();
                filePath = FileUploadConfig.getRelativePath(newFileName);
                
                // 先保存文件到磁盘
                File targetFile = new File(uploadPath + File.separator + newFileName);
                file.transferTo(targetFile);

                // 使用保存的文件进行NLP处理，避免消耗MultipartFile的输入流
                extractedText = nlpProcessor.extractTextFromFile(targetFile);
            }
            
            // 如果有OCR内容，将其添加到提取的文本中
            if (hasOcrContent) {
                if (!extractedText.isEmpty()) {
                    extractedText += "\n" + ocrContent.trim();
                } else {
                    extractedText = ocrContent.trim();
                }
            }

            List<Category> categories = categoryMapper.selectList(null);
            List<Tag> tags = tagMapper.selectList(null);

            // 基于文本内容进行NLP分析，传入数据库查询的分类和标签
            String autoCategory = nlpProcessor.analyzeCategory(extractedText, categories);
            String autoTags = nlpProcessor.analyzeTags(extractedText, tags);

            // Create Archive object and save to database
            Archive archive = new Archive();
            archive.setTitle(title);
            archive.setFilePath(filePath); // 可能为null，如果只有OCR内容
            archive.setOriginalFilename(hasFile ? file.getOriginalFilename() : null); // 保存原始文件名
            archive.setPhysicalLocation(physicalLocation);
            archive.setArchiveType(archiveType);
            archive.setSecurityLevel(securityLevel);
            archive.setVisibleScope(visibleScope);
            archive.setAutoCategory(autoCategory); // Set auto-generated category
            archive.setAutoTags(autoTags);       // Set auto-generated tags
            archive.setOcrContent(hasOcrContent ? ocrContent.trim() : extractedText); // 设置OCR内容，如果没有就用NLP处理后的文件 内容
            archive.setCreatorId(UserContext.getUserId()); // Set creator ID
            archive.setLastModifiedBy(UserContext.getUserId()); // Set last modified by

            Result<Boolean> addResult = archiveService.addArchive(archive);
            if (addResult.getCode() == 200 && addResult.getData()) {
                return Result.success(archive);
            } else {
                // 如果数据库保存失败且有文件，删除已上传的文件
                if (hasFile && filePath != null) {
                    String uploadPath = FileUploadConfig.getUploadPath();
                    String fileName = filePath.replace("uploads" + File.separator, "").replace("uploads/", "");
                    File targetFile = new File(uploadPath + File.separator + fileName);
                    if (targetFile.exists()) {
                        targetFile.delete();
                    }
                }
                return Result.fail(addResult.getCode(), addResult.getMessage());
            }

        } catch (IOException e) {
            logger.error("File upload failed", e);
            return Result.fail(500, "文件上传失败: " + e.getMessage());
        }
    }

    @PutMapping("/update")
    public Result<Boolean> updateArchive(@RequestBody Archive archive) {
        return archiveService.updateArchive(archive);
    }

    @GetMapping("/list")
    public Result<IPage<Archive>> listArchives(@RequestParam(defaultValue = "1") Integer pageNum,
                                                @RequestParam(defaultValue = "10") Integer pageSize,
                                                @RequestParam(required = false) String search,
                                                @RequestParam(defaultValue = "false") Boolean useElasticsearch) {
        Integer userId = UserContext.getUserId();
        logger.debug("UserId from UserContext in ArchiveController: {}", userId);

        PageParam pageParam = new PageParam(pageNum, pageSize, search);
        
        // 根据参数决定使用哪种搜索方式
        if (useElasticsearch) {
            logger.info("使用Elasticsearch搜索，关键词: {}", search);
            return elasticsearchArchiveService.hybridSearch(pageParam, userId);
        } else {
            logger.info("使用MySQL搜索，关键词: {}", search);
            return archiveService.listArchives(pageParam, userId);
        }
    }

    /**
     * 专门的Elasticsearch搜索接口
     * 提供更强大的全文搜索功能
     */
    @GetMapping("/search")
    public Result<IPage<Archive>> searchArchives(@RequestParam(defaultValue = "1") Integer pageNum,
                                                  @RequestParam(defaultValue = "10") Integer pageSize,
                                                  @RequestParam(required = false) String search) {
        Integer userId = UserContext.getUserId();
        logger.info("Elasticsearch搜索请求，用户ID: {}, 关键词: {}", userId, search);

        PageParam pageParam = new PageParam(pageNum, pageSize, search);
        return elasticsearchArchiveService.hybridSearch(pageParam, userId);
    }

    /**
     * 同步档案数据到Elasticsearch
     */
    @PostMapping("/sync/elasticsearch")
    public Result<Boolean> syncToElasticsearch(@RequestParam(required = false) Integer archiveId) {
        if (archiveId != null) {
            // 同步单个档案
            Archive archive = archiveService.getById(archiveId);
            if (archive == null) {
                return Result.fail(404, "档案不存在");
            }
            logger.info("同步单个档案到Elasticsearch，ID: {}", archiveId);
            return elasticsearchArchiveService.syncArchiveToElasticsearch(archive);
        } else {
            // 同步所有档案
            logger.info("开始批量同步所有档案到Elasticsearch");
            return elasticsearchArchiveService.syncAllArchivesToElasticsearch();
        }
    }

    /**
     * 检查Elasticsearch连接状态
     */
    @GetMapping("/elasticsearch/status")
    public Result<Boolean> checkElasticsearchStatus() {
        boolean available = elasticsearchArchiveService.isElasticsearchAvailable();
        logger.info("Elasticsearch连接状态: {}", available ? "可用" : "不可用");
        return Result.success(available);
    }

    @DeleteMapping("/delete/{archiveId}")
    public Result<Boolean> deleteArchive(@PathVariable Integer archiveId) {
        return archiveService.deleteArchive(archiveId);
    }

    /**
     * 下载档案文件
     * 支持权限验证，根据用户角色和档案密级控制下载权限
     * 
     * @param archiveId 档案ID
     * @return 文件下载响应
     */
    @GetMapping("/download/{archiveId}")
    public ResponseEntity<Resource> downloadArchive(@PathVariable Integer archiveId) {
        try {
            Integer userId = UserContext.getUserId();
            if (userId == null) {
                logger.warn("用户未登录，无法下载档案");
                return ResponseEntity.status(401).build();
            }

            // 获取档案信息
            Archive archive = archiveService.getById(archiveId);
            if (archive == null) {
                logger.warn("档案不存在，ID: {}", archiveId);
                return ResponseEntity.notFound().build();
            }

            // 权限验证
            if (!archiveService.canUserAccessArchive(userId, archive)) {
                logger.warn("用户 {} 无权限访问档案 {}", userId, archiveId);
                return ResponseEntity.status(403).build();
            }

            // 检查文件是否存在
            String filePath = archive.getFilePath();
            if (filePath == null || filePath.isEmpty()) {
                logger.warn("档案 {} 没有关联的文件", archiveId);
                return ResponseEntity.notFound().build();
            }

            // 处理不同格式的文件路径
            File file = null;
            String fileName = null;
            
            // 情况1：绝对路径（旧版本数据）
            if (filePath.contains(":") && (filePath.contains("\\") || filePath.contains("/"))) {
                file = new File(filePath);
                fileName = file.getName();
            }
            // 情况2：相对路径 uploads\filename 或 uploads/filename
            else if (filePath.startsWith("uploads")) {
                String uploadPath = FileUploadConfig.getUploadPath();
                fileName = filePath.replace("uploads" + File.separator, "").replace("uploads/", "");
                file = new File(uploadPath + File.separator + fileName);
            }
            // 情况3：无效路径，尝试通过档案标题查找
            else {
                logger.warn("档案 {} 的文件路径格式无效: {}", archiveId, filePath);
                return ResponseEntity.notFound().build();
            }

            if (file == null || !file.exists()) {
                logger.warn("档案文件不存在: {}", file != null ? file.getAbsolutePath() : "null");
                return ResponseEntity.notFound().build();
            }

            // 构建文件下载响应
            Resource resource = new FileSystemResource(file);
            
            // 使用原始文件名，如果没有则从文件名中提取（去掉UUID前缀）
            String downloadFilename;
            if (archive.getOriginalFilename() != null && !archive.getOriginalFilename().isEmpty()) {
                downloadFilename = archive.getOriginalFilename();
            } else {
                // 兼容旧数据：从文件名中提取原始文件名（去掉UUID前缀）
                downloadFilename = fileName;
                if (fileName != null && fileName.contains("_")) {
                    downloadFilename = fileName.substring(fileName.indexOf("_") + 1);
                }
            }

            // URL编码文件名，支持中文
            String encodedFilename = URLEncoder.encode(downloadFilename, "UTF-8").replaceAll("\\+", "%20");

            // 根据文件扩展名确定Content-Type
            MediaType contentType = getContentTypeFromFileName(downloadFilename);

            logger.info("用户 {} 下载档案文件: {} (ID: {}, 文件路径: {})", userId, downloadFilename, archiveId, file.getAbsolutePath());

            return ResponseEntity.ok()
                    .contentType(contentType)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFilename)
                    .body(resource);

        } catch (UnsupportedEncodingException e) {
            logger.error("文件名编码失败", e);
            return ResponseEntity.status(500).build();
        } catch (Exception e) {
            logger.error("下载档案文件失败", e);
            return ResponseEntity.status(500).build();
        }
    }

    /**
     * 根据文件名获取Content-Type
     * 
     * @param fileName 文件名
     * @return MediaType
     */
    private MediaType getContentTypeFromFileName(String fileName) {
        if (fileName == null) {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
        
        String extension = fileName.toLowerCase();
        if (extension.endsWith(".pdf")) {
            return MediaType.APPLICATION_PDF;
        } else if (extension.endsWith(".doc") || extension.endsWith(".docx")) {
            return MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        } else if (extension.endsWith(".xls") || extension.endsWith(".xlsx")) {
            return MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        } else if (extension.endsWith(".ppt") || extension.endsWith(".pptx")) {
            return MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.presentationml.presentation");
        } else if (extension.endsWith(".txt")) {
            return MediaType.TEXT_PLAIN;
        } else if (extension.endsWith(".jpg") || extension.endsWith(".jpeg")) {
            return MediaType.IMAGE_JPEG;
        } else if (extension.endsWith(".png")) {
            return MediaType.IMAGE_PNG;
        } else if (extension.endsWith(".gif")) {
            return MediaType.IMAGE_GIF;
        } else {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
    }

    /**
     * 获取个人档案列表
     * 根据用户ID获取该用户有权限访问的档案
     */
    @GetMapping("/personal-list")
    public Result<IPage<Archive>> listPersonalArchives(@RequestParam(defaultValue = "1") Integer pageNum,
                                                        @RequestParam(defaultValue = "10") Integer pageSize,
                                                        @RequestParam(required = false) String search,
                                                        @RequestParam(required = false) Integer userId) {
        Integer currentUserId = UserContext.getUserId();
        logger.debug("当前用户ID: {}, 请求查询用户ID: {}", currentUserId, userId);

        // 安全检查：只能查看自己的档案
        if (currentUserId == null || !currentUserId.equals(userId)) {
            logger.warn("用户权限不足，当前用户ID: {}, 请求查询用户ID: {}", currentUserId, userId);
            return Result.fail(403, "无权限访问他人档案");
        }

        PageParam pageParam = new PageParam(pageNum, pageSize, search);
        logger.info("获取个人档案列表，用户ID: {}, 搜索关键词: {}", userId, search);
        return archiveService.listPersonalArchives(pageParam, userId);
    }
} 